<?php
namespace App\Http\Services;

use Carbon\Carbon;
use Illuminate\Support\Facades\Redis;
use App\Http\Model\Hint;
use App\Http\Model\Room;
use App\Http\Model\RoomUser;
use App\Http\Model\FinanceUserWallet;
use App\Http\Model\Gift;
use App\Http\Model\RoomHot;
use App\Http\Model\Union;
use App\Http\Model\UnionUser;
use App\Http\Model\RoomMicro;
use App\Http\Model\RoomHostMicro;
use App\Http\Services\RoomMsgServices;
use App\Http\Services\MsgServices;
use App\Http\Model\Musics;
use App\Http\Model\RoomWaitbit;

class NewRoomMicroServices extends CommonServices
{
    protected $roomModel;
    protected $roomUserModel;
    protected $financeUserWalletModel;
    protected $giftModel;
    protected $roomHotModel;
    protected $roomMsgService;
    protected $msgService;
    protected $roomHotService;
    protected $unionUserModel;//公会用户model
    protected $crossRoomPkModel;//pk发起记录
    protected $unionModel;//公会
    protected $roomMicroModel;//普通麦
    protected $roomHostMicroModel;//主持麦
    protected $userBlacklistService;
    protected $musicModel;
    protected $roomWaitbitModel;
    protected $roomUserService;

    protected $micro_lock_key = "micro";//麦位锁定
    protected $crossRoomPkAnchorPkMission = 'CROSS:ROOM:PK:MISSION:ANCHORMIC';//HASH 主播上麦每日PK缓存 CROSS:ROOM:PK:MISSION:ANCHORMIC {$userId}=>time();
    protected $anchorStartLiveTime = 'MICLIVE:START:USER:'; //主播上麦缓存 MICLIVE:START:USER: userid=>time string
    protected $anchorLiveTime = 'MICLIVETIME:USER:';//主播开播总时间秒 MICLIVETIME:USER: userid=>int 

    //房间在麦人数不足计数缓存
    protected $roomMicroFailNumKey = 'ROOM:MICROFAILNUM:';//string ROOM:MICROFAILNUM:{roomOpenId} => {num}
    //房间每单位时间热度缓存
    protected $roomMinuteHotNumKey = 'ROOM:MINUTEHOTNUM:';//hash ROOM:MINUTEHOTNUM:{roomOpenId} => {分钟数}=>{num}
    protected $userPkSendMsgKey = 'CROSS:ROOM:PK:MISSION:SENDMSGUSER:';//用户发言每日PK任务; 

    //拍拍房记录缓存
    protected $roomPaiPaiKey = 'ROOMPAIPAI:LOG:';//hash ROOMPAIPAI:LOG:{roomId} => {string}=>{string}

    public function __construct()
    {
        $this->roomModel = new Room();
        $this->roomUserModel = new RoomUser();
        $this->financeUserWalletModel = new FinanceUserWallet();
        $this->giftModel = new Gift();
        $this->roomHotModel = new RoomHot();


        $this->msgService = new MsgServices();
        $this->roomMsgService = new RoomMsgServices();
        $this->roomUserService = new RoomUserServices();

        $this->roomMicroModel = new RoomMicro();
        $this->roomHostMicroModel = new RoomHostMicro();
        $this->musicModel = new Musics();
        $this->unionModel = new Union();
        $this->unionUserModel = new UnionUser();
        $this->roomWaitbitModel = new RoomWaitbit();

    }

    /**
     * 普通麦上麦数据处理
     */
    public function userMicroIntoForData($roomId, $userId, $microId=null, $sendMsg=1)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            if(empty($userId)) {
                break;
            }
            //是否锁麦
            $microLock = $this->roomMicroModel->getRoomLockMicroByUserId($userId, $roomId);
            if(!empty($microLock)) {
                $code = Hint::ERROR;
                $msg = '已锁麦';
                break;
            }
            if($microId === null) {
                $microId = $this->roomMicroModel->get_into_begin($roomId, $userId);
                if($microId === null) {
                    $code = Hint::ROOM_MICRO_NOT_EXIST;
                    $msg = '未选择上麦麦位';
                    break;
                }
            }
            if($microId === null) {
                $code = Hint::ROOM_MICRO_NOT_EXIST;
                $msg = '未选择上麦麦位';
                break;
            }
            $microId = intval($microId);

            //设置用户在麦的状态
            $this->roomMicroModel->set_user_micro_status($roomId, $userId, $microId, 1);
            //设置麦用户ID
            $this->roomMicroModel->set_user_id($roomId, $microId, $userId);
            //删除上麦前用户麦关系
            $this->roomMicroModel->del_into_begin($roomId, $userId);
            //解除麦位锁定
            redis_unlock($this->micro_lock_key.$roomId);
    
            //跨房PK每日任务
            $this->crossRoomPkMissionMic($userId, $roomId);

            //普通麦上麦通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_micro_into($roomId, $microId, $userId);
            }

            // 主播设置了全麦闭麦， 上麦用户自动闭麦
            if ($this->roomModel->get_volume_closed($roomId) == 1) {
                $this->roomMicroModel->volume_close($roomId, $microId);
                //普通麦闭麦指令
                if($sendMsg) {
                    $this->roomMsgService->command_micro_volume_close($roomId, $microId, 0);
                }
                //普通麦闭麦通知
                if($sendMsg) {
                    $this->roomMsgService->broadcast_micro_volume_close($roomId, $microId, 0);
                }
            }
            //默认闭麦 sn
            $this->roomMicroModel->volume_self_close($roomId, $microId);
            //普通麦闭麦指令
            if($sendMsg) {
                $this->roomMsgService->command_micro_volume_close($roomId, $microId, 1);
            }
            //普通麦闭麦通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_micro_volume_close($roomId, $microId, 1);
            }
            //设置删除抱麦
            $this->roomMicroModel->del_hold($roomId, $microId);

            // 删除待麦用户
            $this->roomWaitbitModel->del_user($roomId, $userId);
            //删除排麦通知
            $this->roomMsgService->broadcast_micro_waitbit_del($roomId, $userId);
            //记录主播开播上麦时间
            Redis::set($this->anchorStartLiveTime.$userId, time());

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 主持麦上麦数据处理
     */
    public function userHostMicroIntoForData($roomId, $userId, $sendMsg=1)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            $micro_id = $this->roomHostMicroModel->get_into_begin($roomId, $userId);
            if ($micro_id === null){
                $code = Hint::ROOM_MICRO_NOT_EXIST;
                $msg = '未选择上麦麦位';
                break;
            }
            //设置用户上麦状态
            $this->roomHostMicroModel->set_user_status($roomId, $userId, 1);
            //设置主持麦用户
            $this->roomHostMicroModel->set_user_id($roomId, $userId);
            //删除上麦前用户麦关系
            $this->roomHostMicroModel->del_into_begin($roomId, $userId);
            //删除房间关闭时间
            $this->roomModel->del_close_timestamp($roomId);
            //标记房间是开启
            $this->roomModel->set_opened($roomId);
            //解除麦位锁定
            redis_unlock($this->micro_lock_key.$roomId);

            //主持麦上麦通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_hostmicro_into($roomId, 0, $userId);
            }
            //开播消息
            $this->msgService->room_opened($roomId, $userId);

            // 删除待麦用户
            $this->roomWaitbitModel->del_user($roomId, $userId);
            //删除排麦通知
            $this->roomMsgService->broadcast_micro_waitbit_del($roomId, $userId);
            //记录主播开播上麦时间
            Redis::set($this->anchorStartLiveTime.$userId, time());

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 普通麦下麦数据处理
     */
    public function userMicroOutForData($roomId, $userId, $microId=null, $sendMsg=1, $sendOrder=1)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            if(empty($userId)) {
                break;
            }
            //是否锁麦
            $microLock = $this->roomMicroModel->getRoomLockMicroByUserId($userId, $roomId);
            if(!empty($microLock)) {
                $code = Hint::ERROR;
                $msg = '已锁麦';
                break;
            }

            //删除播放音乐权限
            $this->musicModel->delMusicPermission($roomId, $userId);

            //获取用户上麦状态
            $microInfo = $this->roomMicroModel->get_user_micro_status($roomId, $userId);
            if(empty($microInfo)) {
                $code = Hint::ROOM_MICRO_NOT_EXIST;
                $msg = '获取用户上麦状态失败';
                break;
            }
            if($microId === null) {
                $microId = (int) $microInfo['micro_id'];
            }else{
                if($microId != $microInfo['micro_id']) {
                    $code = Hint::ROOM_MICRO_NOT_EXIST;
                    $msg = '用户已经不在这个麦位了';
                    break;
                }
            }
            if($microId === null) {
                $code = Hint::ROOM_MICRO_NOT_EXIST;
                $msg = '用户已经不在这个麦位了';
                break;
            }

            $microId = (int) $microId;
            //移除用户的上麦状态
            $this->roomMicroModel->del_user_micro_status($roomId, $userId);
            //删除麦用户
            $this->roomMicroModel->del_user_id($roomId, $microId);
            //解除麦位锁定
            redis_unlock($this->micro_lock_key.$roomId);
            //删除跨房PK每日任务主播上麦记录
            Redis::DEL($this->crossRoomPkAnchorPkMission);

            //普通麦下麦指令
            if($sendOrder) {
                $this->roomMsgService->command_micro_out($roomId, $microId, $userId);
            }

            //普通麦下麦通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_micro_out($roomId, $microId, $userId);
            }

            //删除麦礼物信息
            $gift_data = $this->roomMicroModel->get_gift($roomId, $microId);
            if (!empty($gift_data)){
                $this->roomMicroModel->del_gift($roomId, $microId);
            }

            //取消麦礼物通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_micro_ungift($roomId, $microId);
            }

            //删除开播的记录,并统计主播开播时长
            $startMicTime = Redis::get($this->anchorStartLiveTime.$userId);
            if(!empty($startMicTime)){
                //记录下播时间到现在一共开了多常时间
                $diffSecond = $now - date('Y-m-d H:i:s',$startMicTime);
                //累加主播开播时间
                Redis::INCRBY($this->anchorLiveTime.$userId, $diffSecond);
                //删除
                Redis::DEL($this->anchorStartLiveTime.$userId);
            }

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 主持麦下麦数据处理
     */
    public function userHostMicroOutForData($roomId, $userId, $sendMsg=1, $sendOrder=1)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            //删除播放音乐权限
            $this->musicModel->delMusicPermission($roomId, $userId);
            //移除用户上麦状态
            $this->roomHostMicroModel->del_user_status($roomId, $userId);
            //删除麦
            $this->roomHostMicroModel->del_user_id($roomId);
            //设置房间关闭时间
            $timestamp = time() + 9999999;
            $this->roomModel->set_close_timestamp($roomId, $timestamp);
            //添加房间到待删除列表
            $this->roomModel->add_wait_close($roomId);
            //解除麦位锁定
            redis_unlock($this->micro_lock_key.$roomId);

            //主持麦下麦指令
            if($sendOrder) {
                $this->roomMsgService->command_hostmicro_out($roomId, 0, $userId);
            }

            //主持麦下麦通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_hostmicro_out($roomId, 0, $timestamp, $userId);
            }

            //删除麦礼物信息
            $gift_data = $this->roomHostMicroModel->get_gift($roomId);
            if (!empty($gift_data)){
                $this->roomHostMicroModel->del_gift($roomId);
            }

            //取消主持麦礼物通知
            if($sendMsg) {
                $this->roomMsgService->broadcast_hostmicro_ungift($roomId, 0);
            }

            //删除开播的记录,并统计主播开播时长
            $startMicTime = Redis::get($this->anchorStartLiveTime.$userId);
            if(!empty($startMicTime)){
                //删除
                Redis::DEL($this->anchorStartLiveTime.$userId);
            }

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 用户离开房间数据处理
     */
    public function roomUserQuitForData($roomId, $userId, $sendMsg=1)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            //是否锁麦
            $microLock = $this->roomMicroModel->getRoomLockMicroByUserId($userId, $roomId);
            if(!empty($microLock)) {
                $code = Hint::ROOM_MICRO_USER_LOCK;
                break;
            }

            //主持麦用户ID
            $roomMicroHostUserId = $this->roomHostMicroModel->get_user_id($roomId);
            //普通麦
            $microInfo = $this->roomMicroModel->get_user_micro_status($roomId, $userId);
            $microId = empty($microInfo) ? -1 : $microInfo['micro_id'];

            //普通麦
            if($microId >= 0) {
                //拍拍房
                $cacheKey = $this->roomPaiPaiKey.$roomId;
                $info = Redis::HGETALL($cacheKey);
                if(!empty($info)) {
                    if((in_array($microId, [1,2]) && !empty($info['score_12']))
                    || (in_array($microId, [3,4]) && !empty($info['score_34']))
                    || (in_array($microId, [5,6]) && !empty($info['score_56']))
                    ) {
                        if($microId == 1) {
                            $toMicroId = 2;
                        }
                        if($microId == 2) {
                            $toMicroId = 1;
                        }
                        if($microId == 3) {
                            $toMicroId = 4;
                        }
                        if($microId == 4) {
                            $toMicroId = 3;
                        }
                        if($microId == 5) {
                            $toMicroId = 6;
                        }
                        if($microId == 6) {
                            $toMicroId = 5;
                        }
                        $toMicroUserId = $this->roomMicroModel->get_user_id($roomId, $toMicroId);
                        if($toMicroUserId == 0) {
                            break;
                        }

                        $code = Hint::ROOM_PAIPAI_LOCK;
                        break;
                    }
                }

                $this->userMicroOutForData($roomId, $userId);
            }
            //主持麦
            if($roomMicroHostUserId == $userId) {
                $this->userHostMicroOutForData($roomId, $userId);
            }

            //删除播放音乐权限
            $this->musicModel->delMusicPermission($roomId, $userId);

            //删除房间用户缓存
            $this->roomUserService->callback_del($roomId, $userId);

            // 删除待麦用户
            $this->roomWaitbitModel->del_user($roomId, $userId);
            //删除排麦通知
            $this->roomMsgService->broadcast_micro_waitbit_del($roomId, $userId);

            //离开房间通知
            $this->roomMsgService->broadcast_user_out($roomId, $userId);

        } while (false);

        return compact('code', 'msg', 'data');
    }

    /**
     * 判断用户是否可以离开房间或下麦
     */
    public function checkRoomUserCanQuit($roomId, $userId)
    {
        $code = Hint::SUCCESS;
        $msg = '';
        $data = [];
        $now = time();

        do {
            if(empty($roomId) || empty($userId)) {
                break;
            }
            //是否锁麦
            $microLock = $this->roomMicroModel->getRoomLockMicroByUserId($userId, $roomId);
            if(!empty($microLock)) {
                $code = Hint::ROOM_MICRO_USER_LOCK;
                break;
            }

            //普通麦
            $microInfo = $this->roomMicroModel->get_user_micro_status($roomId, $userId);
            $microId = empty($microInfo) ? -1 : $microInfo['micro_id'];
            $data['micro_id'] = $microId;

            //普通麦
            if($microId > -1) {
                //拍拍房
                $cacheKey = $this->roomPaiPaiKey.$roomId;
                $info = Redis::HGETALL($cacheKey);
                if(!empty($info)) {
                    if((in_array($microId, [1,2]) && !empty($info['score_12']))
                    || (in_array($microId, [3,4]) && !empty($info['score_34']))
                    || (in_array($microId, [5,6]) && !empty($info['score_56']))
                    ) {
                        if($microId == 1) {
                            $toMicroId = 2;
                        }
                        if($microId == 2) {
                            $toMicroId = 1;
                        }
                        if($microId == 3) {
                            $toMicroId = 4;
                        }
                        if($microId == 4) {
                            $toMicroId = 3;
                        }
                        if($microId == 5) {
                            $toMicroId = 6;
                        }
                        if($microId == 6) {
                            $toMicroId = 5;
                        }
                        $toMicroUserId = $this->roomMicroModel->get_user_id($roomId, $toMicroId);
                        if($toMicroUserId == 0) {
                            break;
                        }

                        $code = Hint::ROOM_PAIPAI_LOCK;
                        break;
                    }
                }
            }

        } while (false);

        return compact('code', 'msg', 'data');
    }

    //跨房PK主播上麦每日任务
    public function crossRoomPkMissionMic($user_id, $room_id){
        //每日主播上麦任务PK
        $isAnchor = 0;
        $res = $this->unionUserModel->userToUnion($user_id);
        if(!empty($res)){
            //查看公会是否认证
            $checkStatus = $this->unionModel->getUnions([$res['un_id']]);
            if(isset($checkStatus[0]['authentication_status']) && $checkStatus[0]['authentication_status'] != 0){
                $isAnchor = 1;
            }
        }
        //查寻房间是否在PK中
        $roomMode = $this->roomModel->getRoomOpenList($room_id, 'roomMode');
        if(empty(Redis::HGET($this->crossRoomPkAnchorPkMission,$user_id)) && $isAnchor && $roomMode == 6){
            Redis::HSET($this->crossRoomPkAnchorPkMission,$user_id,time());
            //计算结束当天所差秒数
            $now = Carbon::now()->toDateTimeString();
            $endDay = Carbon::now()->endOfDay()->toDateTimeString();
            $diffTime = Carbon::parse($now)->diffInSeconds($endDay);
            Redis::EXPIRE($this->crossRoomPkAnchorPkMission,$diffTime);//当前时间到今日截止时间
        }
    }


}
